const {
	Service
} = require("uni-cloud-router");
const {
	result_success,
	result_error
} = require('http-result-modle')
const fs = require('fs')
const path = require('path')
const crypto = require("crypto");
module.exports = class EncryptUtillsServcice extends(
	Service
) {

	/**
	 * @param {Object} dataInfo{data:加密数据, encode:数据编码格式}
	 * @param {Object} privateKeyFileName 秘钥文件名称，统一放在wmz-crypto/doc/ 目录下
	 * @param {Object} privateKey 秘钥，优先于秘钥文件名称
	 */
	async sha256WithRsaToBase64(dataInfo, privateKeyFileName, privateKey) {
		if (!privateKey && !privateKeyFileName) {
			return result_error("privateKey秘钥不能为空")
		}
		if (!privateKey && privateKeyFileName) {
			let fileUrl = '../doc'
			fileUrl = fileUrl + "/" + privateKeyFileName
			privateKey = fs.readFileSync(path.resolve(__dirname, fileUrl)).toString()
		}
		return this.cryptoSign(dataInfo, privateKey, "sha256", "base64")
	}

	async sha256To(dataInfo) {
		let cryp = crypto.createHash("sha256").update(dataInfo).digest("hex")
		return result_success(cryp)
	}

	/**
	 * crypto签名算法
	 * @param {Object} dataInfo{data:加密数据, encode:数据编码格式}
	 * @param {Object} privateKey 加密秘钥
	 * @param {Object} rsaCode 加密方式
	 * @param {Object} encode 返回数据编码方式
	 */
	async cryptoSign(dataInfo, privateKey, rsaCode, encode) {
		// 第一步：用私钥对传输的数据，生成对应的签名
		if (!rsaCode) {
			rsaCode = "sha256"
		}
		if (!encode) {
			encode = "base64"
		}
		const sign = crypto.createSign(rsaCode);
		// 添加数据
		if (!dataInfo.encode) {
			dataInfo.encode = "utf-8"
		}
		sign.update(dataInfo.data, dataInfo.encode);
		sign.end();
		// 根据私钥，生成签名
		const signature = sign.sign(privateKey, encode);
		return result_success(signature)
	}

	/**
	 * 微信敏感信息加密
	 * @param {Object} dataInfo 加密数据
	 * @param {Object} privateKeyFileName 秘钥文件名称，统一放在wmz-crypto/doc/ 目录下
	 * @param {Object} privateKey 秘钥，优先于秘钥文件名称
	 */
	async encryptSensitiveInfoWx(dataInfo, privateKeyFileName, privateKey) {
		if (!privateKey && !privateKeyFileName) {
			return result_error("privateKey秘钥不能为空")
		}
		if (!privateKey && privateKeyFileName) {
			let fileUrl = '../doc'
			fileUrl = fileUrl + "/" + privateKeyFileName
			privateKey = fs.readFileSync(path.resolve(__dirname, fileUrl)).toString()
		}
		let encryptStr
		try {
			const encryptText = crypto.publicEncrypt({
				key: Buffer.from(privateKey),
				padding: crypto.constants.RSA_PKCS1_OAEP_PADDING
			}, Buffer.from(dataInfo, "utf-8"));
			encryptStr = encryptText.toString("base64");
		} catch (e) {
			//TODO handle the exception
		}
		return result_success(encryptStr)
	}

	/**
	 * 微信平台证书验签解密
	 * @param {Object} ciphertext
	 * @param {Object} nonce
	 * @param {Object} apiV3Key
	 * @param {Object} associated_data
	 */
	async decodeV3CertificatesWx(ciphertext, nonce, apiV3Key, associated_data) {
		let encrypted = Buffer.from(ciphertext, 'base64')
		let decipher = crypto.createDecipheriv('aes-256-gcm', apiV3Key, nonce)
		decipher.setAuthTag(encrypted.slice(-16))
		decipher.setAAD(Buffer.from(associated_data))
		let output = Buffer.concat([
			decipher.update(encrypted.slice(0, -16)),
			decipher.final()
		])
		return result_success(output)
	}
};
